
#pragma once
#include <brpc/channel.h>
#include <brpc/controller.h>
#include <brpc/naming_service.h>
#include <cstddef>
#include <log.h>
#include <memory>
#include <odb/mysql/database.hxx>

#include "brpc.h"
#include "httplib.h"
// #include "storage.pb.h"
#include "user.pb.h"
#include "etcd_path.h"


using namespace std;

class UserModule {
private:
    std::shared_ptr<brpc::Channel> _channel;
    std::shared_ptr<user::UserService_Stub> _stub;
public:
    using ptr = std::shared_ptr<UserModule>;
    UserModule(const std::string &etcd_path) {
        _channel = lyt::build_etcd(etcd_path, lyt::user_path);
        _stub = make_shared<user::UserService_Stub>(_channel.get());
    }
    void userSendCode(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给验证码模块
        */
        user::VerificationCodeRequest verifycodeRequest;
        user::VerificationCodeResponse verifycodeResponse;
        if (!verifycodeRequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid data", "text/plain");
            return;
        }
        brpc::Controller cntl;
        _stub->SendCode(&cntl, &verifycodeRequest, &verifycodeResponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        string res_bin;
        verifycodeResponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void userRegister(const httplib::Request &req, httplib::Response &res) {
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给用户注册模块
        */
        // 1.
        user::RegisterRequest registerRequest;
        user::RegisterResponse registerResponse;
        // 2.
        if (!registerRequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->Register(&cntl, &registerRequest, &registerResponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        registerResponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void userLogin(const httplib::Request &req, httplib::Response &res) {
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给密码登录模块
        */
        // 1.
        debuglog << "In UserLogin"; 
        user::LoginRequest LoginRequest;
        user::LoginResponse LoginResponse;
        // 2.
        if (!LoginRequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 打印日志，把请求的各个字段打印一下，看请求到了后端服务没，没 肯定 刚才我注册的时候也有这个提示
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        // 应该是rpc的时候超时了
        _stub->Login(&cntl, &LoginRequest, &LoginResponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            debuglog << "RPC Failed: "<<cntl.ErrorText();
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        debuglog << "rpc request success";
        // 返回消息
        string res_bin;
        LoginResponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
        debuglog << "return response success";
    }
    void userCodeLogin(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给验证码登录模块
        */
        // 1.
        debuglog << "In userCodeLogin";
        user::CodeLoginRequest CodeLoginRequest;
        user::LoginResponse LoginResponse;
        // 2.
        if (!CodeLoginRequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->CodeLogin(&cntl, &CodeLoginRequest, &LoginResponse, nullptr);
        if (cntl.Failed()) {
            debuglog << "cntl.Failed" << cntl.ErrorText();
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        LoginResponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
        debuglog << "out userCodeLogin";
        
    }
    void getUserstats(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给获取用户状态模块
        */
        // 1.
        user::UserStatsRequest userstatsquest;
        user::UserStatsResponse userstatsresponse;
        // 2.
        if (!userstatsquest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 

        brpc::Controller cntl;
        _stub->GetUserstats(&cntl, &userstatsquest, &userstatsresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        userstatsresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void getUserstatssummary(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给获取用户概要状态模块
        */
        // 1.
        user::UserStatsSummaryRequest userstatssummaryrequest;
        user::UserStatsSummaryResponse userstatssummaryrespnse;
        // 2.
        if (!userstatssummaryrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 
        brpc::Controller cntl;
        _stub->GetUserstatsSummary(&cntl, &userstatssummaryrequest, &userstatssummaryrespnse, nullptr);
        if (cntl.Failed()) {
            debuglog << "GetUserstatsSummary cntl failed" << cntl.ErrorText();
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        userstatssummaryrespnse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void userLogout(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给用户登出模块
        */
        // 1.
        user::LogoutRequest logoutrequest;
        user::LogoutResponse logoutresponse;
        // 2.
        if (!logoutrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 
        brpc::Controller cntl;
        _stub->Logout(&cntl, &logoutrequest, &logoutresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        logoutresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void updateUsername(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户名模块
        */
        // 1.
        user::UpdateUsernameRequest updateusernamerequest;
        user::UpdateUsernameResponse updateusernameresponse;
        // 2.
        if (!updateusernamerequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 
        brpc::Controller cntl;
        _stub->Updateusername(&cntl, &updateusernamerequest, &updateusernameresponse, nullptr);
        if (cntl.Failed()) {
            debuglog << "cntlFailed!";
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        updateusernameresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void updateuserAvatar(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新头像模块
        */
        // 1.
        user::UpdateAvatarRequest updateavatarrequest;
        user::UpdateAvatarResponse updateavatarresponse;
        // 2.
        if (!updateavatarrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->Updateuseravatar(&cntl, &updateavatarrequest, &updateavatarresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        updateavatarresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void updateuserPassword(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码
        */
        // 1.
        user::ChangePasswordRequest changepasswordrequest;
        user::ChangePasswordResponse changepasswordresponse;
        // 2.
        if (!changepasswordrequest.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->UpdatePassword(&cntl, &changepasswordrequest, &changepasswordresponse, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        changepasswordresponse.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void updateuserPasswordbyemail(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码通过邮箱模块
        */
        // 1.
        user::ChangePasswordByEmailRequest changepwdbyemailreq;
        user::ChangePasswordResponse changepwdres;
        // 2.
        if (!changepwdbyemailreq.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->UpdatePasswordByEmail(&cntl, &changepwdbyemailreq, &changepwdres, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        changepwdres.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void getFllowstats(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码通过邮箱模块
        */
        // 1.
        user::GetFollowStatusRequest getfollowstatsreq;
        user::GetFollowStatusResponse getfollowstatsres;
        // 2.
        if (!getfollowstatsreq.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->GetFollowsStatus(&cntl, &getfollowstatsreq, &getfollowstatsres, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        getfollowstatsres.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void Follow(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码通过邮箱模块
        */
        // 1.
        user::FollowRequest followreq;
        user::FollowResponse followres;
        // 2.
        if (!followreq.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->Follow(&cntl, &followreq, &followres, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        followres.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void UnFollow(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码通过邮箱模块
        */
        // 1.
        user::UnfollowRequest unfollowreq;
        user::UnfollowResponse unfollowres;
        // 2.
        if (!unfollowreq.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->UnFollow(&cntl, &unfollowreq, &unfollowres, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        unfollowres.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void getUserinfo(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码通过邮箱模块
        */
        // 1.
        user::GetUserInfoRequest getuserinforeq;
        user::GetUserInfoResponse getuserinfores;
        // 2.
        if (!getuserinforeq.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->GetUserInfo(&cntl, &getuserinforeq, &getuserinfores, nullptr);
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        getuserinfores.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
    }
    void getDefaultavatar(const httplib::Request &req, httplib::Response &res){
        /*
            1. 创建proto请求对象与响应对象
            2. 解析二进制数据
            3. 交给更新用户密码通过邮箱模块
        */
        // 1.
        user::GetDefaultAvatarRequest getdefaultavatarreq;
        user::GetDefaultAvatarResponse getdefaultavatarres;
        // 2.
        if (!getdefaultavatarreq.ParseFromArray(req.body.data(), req.body.size())) {
            res.status = 400;
            res.set_content("Invalid protobuf data", "text/plain");
            return;
        }
        // 3. 构建channel，服务发现
        brpc::Controller cntl;
        _stub->GetDefaultAvatar(&cntl, &getdefaultavatarreq, &getdefaultavatarres, nullptr);
        infolog << "GetDefaultAvatar success";
        if (cntl.Failed()) {
            res.status = 500;
            res.set_content("RPC Failed: " + cntl.ErrorText(), "text/plain");
            return;
        }
        // 返回消息
        string res_bin;
        infolog << "get avatar success";
        getdefaultavatarres.SerializeToString(&res_bin);
        res.status = 200;
        res.set_content(res_bin, "application/octet-stream");
        infolog << "return get avatar";
    }
};